
(function(){
	HemiEngine.include("hemi.util");
	HemiEngine.include("hemi.object");
	HemiEngine.include("hemi.object.xhtml");
	HemiEngine.include("hemi.task");
	HemiEngine.include("hemi.wires");
	HemiEngine.include("hemi.data.form");
	HemiEngine.include("hemi.logger");
	HemiEngine.namespace("app.space", HemiEngine, {
		service:null,
		serviceImpl:function(){
			var t=this,
				_j=org.cote.js,
				_x=HemiEngine.xml,
				_m=HemiEngine.message.service
			;
			
			Hemi.util.logger.addLogger(t, "Space", "Application Space", "600");

			t.properties = {
				pn:"space_loader",
				pa:"[nothing]",
				pat:"default",
				ph:"space_initialized",
				pht:"event",
				
				dn:"space",
				da:"[nothing]",
				dat:"default",
				dh:"space_initialized",
				dht:"event",

				space_autoid_counter:0,
				space_id_counter:0,
				space_id_label:"hemi.space",
				
				/* automatically load spaces when window.onload fires */
				auto_load:1,

				/* name of the task that loaded the configuration, if any */
				/* page_config_task */
				config_task:"load_space_config",

				/* name of the space configuration to use as a default */
				config_default:0
					
			};
			t.objects = {
				local_task_service:new Hemi.task.serviceImpl()
				local_wire_service:new Hemi.wires.serviceImpl()
			};

			t.getWireService = function(){
				return t.objects.local_wire_service;
			};

	///		<method>
	///			<name>getTaskService</name>
	///			<return-value name = "t" type = "TaskService">Instance of a TaskService.</return-value>
	///			<description>Returns the TaskService used by this EngineService instance.</description>
	///		</method>
			t.getTaskService = function(){
				return t.objects.local_task_service;
			};

			/*
				AutoLoad is only valid prior to the window.onload event firing
			*/
	///		<method>
	///			<name>setAutoLoad</name>
	///			<param name = "b" type = "boolean">Bit indicating whether auto-loading is enabled.</param>
	///			<description>Specifies whether all engines should start loading automatically after the window onload event fires.  Auto loading is only effective when set prior to the window loading.</description>
	///		</method>
			t.setAutoLoad=function(b){
				t.properties.auto_load = (b?1:0);
			};

	///		<method>
	///			<name>setConfigurationTaskName</name>
	///			<param name = "s" type = "String">The name of the task that loads the configuration file for the engine service.</param>
	///			<description>Specifies the name of the task responsible for loading any external configuration for this EngineService instance.  The default value is <i>load_engine_config</i>.</description>
	///		</method>
			t.setConfigurationTaskName=function(s){
				t.properties.config_task = s;
			};

	///		<method>
	///			<name>setDefaultConfiguration</name>
	///			<param name = "s" type = "String">The default configuration name to use when loading an engine and when the engine does not specify a configuration.</param>
	///			<description>Sets the default configuration name.  The configuration name should match an EngineService configuration file entry.</description>
	///		</method>
			t.setDefaultConfiguration=function(s){
				t.properties.config_default = s;
			};

	///		<method>
	///			<name>setPrimaryEngineAction</name>
	///			<param name = "s" type = "String">The action to perform for the primary engine.</param>
	///			<description>Sets the action to perform for the primary engine, if that engine did not define a different action.  The default is no action.</description>
	///		</method>
			t.setPrimarySpaceAction=function(s){
				t.properties.pa = s;
			};

	///		<method>
	///			<name>setPrimaryEngineActionType</name>
	///			<param name = "s" type = "String">The type of action to perform for the primary engine.</param>
	///			<description>Sets the type of action to perform for the primary engine, if that engine did not define a different action type.  The default is nothing.</description>
	///		</method>
			t.setPrimarySpaceActionType=function(s){
				t.properties.pat = s;
			};

	///		<method>
	///			<name>setPrimaryEngineHandler</name>
	///			<param name = "s" type = "String">The handler to perform for the primary engine.</param>
	///			<description>Sets the handler to perform for the primary engine, if that engine did not define a different handler.  The default is <i>engine_service_initialized</i>.</description>
	///		</method>
			t.setPrimarySpaceHandler=function(s){
				t.properties.ph = s;
			};

	///		<method>
	///			<name>setPrimaryEngineHandlerType</name>
	///			<param name = "s" type = "String">The type of handler to perform for the primary engine.</param>
	///			<description>Sets the type of handler to perform for the primary engine, if that engine did not define a different handler type.  The default is <i>event</i>.</description>
	///		</method>
			t.setPrimarySpaceHandlerType=function(s){
				t.properties.pht = s;
			};

	///		<method>
	///			<name>getComponentFromSpace</name>
	///			<param name = "i" type = "String">Identifier of a space.</param>
	///			<param name = "c" type = "String">Identifier of a component created for the enigne.</param>
	///			<param name = "b" type = "boolean">Bit indicating whether the component container should be returned, if a container exists.</param>
	///			<return-value name = "o" type = "object">Returns an XHTMLComponent, ApplicationComponent, or DOM Node, depending on the specified parameters.  If not returning the container, then the return object will be an object registered with the ObjectRegistry.</return-value>
	///			<description>Returns the specified component from the specified engine.</description>
	///		</method>
			t.getComponentFromSpace=function(i,c,b){
					/*
						i = engine id
						c = component id
						b = switch to return the object, or the object container
					*/
				var _m = HemiEngine.message.service,
					e,
					o
				;
				e = t.getSpace(i);
				if(!t.isSpace(e)){
					_m.sendMessage("Invalid engine reference","200.4",1);
					return 0;
				}
				o = e.getObjectByName(c);
				if(!o){
					this.logError("Invalid engine component reference '" + c + "'","1.1");
					return 0;
				}
				if(DATATYPES.TO(o.object)){
					if(!b){
						return o.object
					}
					else if(DATATYPES.TF(o.object.getContainer)){
						return o.object.getContainer();
					}
				}

				return 0;

			};

	///		<method>
	///			<name>sigterm</name>
	///			<description>Sends a termination signal to this object.</description>
	///		</method>
			t.sigterm = function(){
				this.destroy();
			};

	///		<method>
	///			<name>destroy</name>
	///			<description>Prepares this object for destruction, and destroys all Engine objects.</description>
	///		</method>
			t.destroy = function(){
				var t = this,_m = HemiEngine.message.service;
				if(t.ready_state != 5){

					_m.unsubscribe(t,"dom_event_window_load","handle_window_load");
					_m.unsubscribe(t,"space_started","handle_engine_started");
					_m.unsubscribe(t,"space_service_initialized","handle_engine_service_initialized");

					t.ready_state = 5;
					t.clearSpaces();
				}
			};

	///		<method>
	///			<name>clearSpace</name>
	///			<param name = "i" type = "variant">Name or object reference of the Engine object to clear.</param>
	///			<description>Clears the specified Engine object, and destroys all components of the Engine.</description>
	///		</method>
			t.clearSpace = function(i){
				var _p = t.objects,o,b,h;

				if(typeof i == DATATYPES.TYPE_STRING) o = t.getSpace(i);
				if(typeof i == DATATYPES.TYPE_OBJECT) o = i;
				
				if(t.isEngine(o)){
					
					b = o.space_objects;
					for(h = b.length - 1; h >= 0; h--){
						HemiEngine.registry.service.sendDestroyTo(b[h].object);
					}
					
					/// 2007/02/03
					/// Clear out any XHTMLForm references to this Engine
					///
					HemiEngine.data.form.service.removeForm(o.engine_id);

					o.space_objects = [];
					o.space_object_names = [];
					o.space_object_index = [];
					
					
					o.space_implementations = [];
					
					
					if(o.space_element){
						
						%START_DEBUG_MESSAGE%
						HemiEngine.message.service.sendMessage("Clear engine " + o.engine_id,"200.1");
						%STOP_DEBUG_MESSAGE%
						
						_x.removeChildren(o.space_element);
						if(o.space_element.parentNode) o.space_element.parentNode.removeChild(o.space_element);
					}
					

					_p.spaces[o.engine_index] = null;
					_p.engineindex[o.engine_id] = null;
					_p.enginenames[o.engine_name] = null;
					
					%START_DEBUG_MESSAGE%
					_m.sendMessage("Clear engine '" + i + "'","200.1");
					%STOP_DEBUG_MESSAGE%
				}
				else{
					_m.sendMessage("Invalid engine reference '" + i + "'","200.4");
				}
			};

	///		<method>
	///			<name>clearSpaces</name>
	///			<description>Clears all Engine objects, and destroys all components in each Engine.</description>
	///		</method>
			t.clearSpaces=function(){

				var _p = t.objects,a,i,o,h,b,_t;
				a = _p.spaces;
				_t = _p.local_task_service;
				
				/*
					Clean up any objects associated with the engines
				*/
				
				for(i = a.length - 1;i >= 0; i--){
					t.clearSpace(a[i]);

	/*
					b = a[i].space_objects;
					for(h=b.length-1;h>=0;h--){
						HemiEngine.registry.service.sendDestroyTo(b[h].object);
					}
	*/			
				}

				_p.spaces = [];
				_p.engineindex = [];
				_p.enginenames = [];
				/*
				for(i = 0;i<a.length;i++){
					o = a[i];
					_t.clearTask(o.task);
				}
				*/
				
				_t.clearTasks();

				%START_DEBUG_MESSAGE%			
				_m.sendMessage("Reset engine information.","200.1");
				%STOP_DEBUG_MESSAGE%

			};
			

	///		<method>
	///			<name>getPrimaryEngine</name>
	///			<return-value name = "e" type = "Engine">The primary Engine object.</return-value>
	///			<description>Returns the Engine object that is the primary engine for the service.</description>
	///		</method>
			t.getPrimaryEngine = function(){
				return t.getSpaceByName(t.properties.pn);
			};

			t.handle_window_load=function(){
	/*			_m.sendMessage("Engine Service Init","200.1");*/
				if(t.properties.auto_load) t.loadSpaces();
			};
			
	///		<method internal = "1">
	///			<name>newSpaceObject</name>
	///			<param name = "e" type = "Node">XHTML Element representing the engine.</param>
	///			<param name = "i" type = "String">Unique identifier.</param>
	///			<param name = "n" type = "String">Friendly name for the object.</param>
	///			<param name = "k" type = "TaskObject">Task object used to load this engine.</param>
	///			<param name = "x" type = "int">Index of engine relative to adjacent engines.</param>
	///			<return-value name = "o" type = "EngineObject">New engine object.</return-value>
	///			<description>Creates a new Engine object.</description>
	///		</method>
			t.newSpaceObject = function(e, i, n, k, x){
				var e = {
					space_element:e,
					engine_id:i,
					engine_name:n,
					engine_index:x,
					config_name:0,
					task:k,
					is_primary:0,
					engine_objects:[],
					space_object_names:[],
					engine_object_index:[],
					Processor:function(o,n){},
					XhtmlHandler:0,
					
					space_implementations:[],
					
					
					getContainer:function(){return this.space_element;},
					getObjects:function(){return this.space_objects;},
					getObject:function(i){if(typeof this.space_object_index[i] == DATATYPES.TYPE_NUMBER && typeof this.space_objects[this.space_object_index[i]]==DATATYPES.TYPE_OBJECT){return this.space_objects[this.space_object_index[i]];}return 0;},
					isObject:function(n){if(typeof n == DATATYPES.TYPE_STRING &&	typeof this.space_object_names[n] == DATATYPES.TYPE_NUMBER && typeof this.space_objects[this.space_object_names[n]] == DATATYPES.TYPE_OBJECT){return 1;}return 0;},
					getObjectByName:function(n){if(typeof n == DATATYPES.TYPE_STRING && typeof this.space_object_names[n] == DATATYPES.TYPE_NUMBER && typeof this.space_objects[this.space_object_names[n]] == DATATYPES.TYPE_OBJECT){return this.space_objects[this.space_object_names[n]];}return 0;},
					primitive_wires:[],
					getPrimitiveWire:function(i){if(typeof i == DATATYPES.TYPE_STRING && typeof this.primitive_wires[i] != DATATYPES.TYPE_UNDEFINED) return this.primitive_wires[i];return 0;},
					ds:0,
					setDataSource:function(s){this.ds = s;},
					getDataSource:function(){return this.ds;},
					dp:0,
					setDataPath:function(s){this.dp = s;},
					getDataPath:function(){return this.dp;},
					data_variant:[],
					setDataVariant:function(i,v){if(typeof i == DATATYPES.TYPE_NUMBER){this.data_variant[i] = v;return 1} return 0;},
					getDataVariant:function(i){if(typeof i == DATATYPES.TYPE_NUMBER && typeof this.data_variant[i] != DATATYPES.TYPE_UNDEFINED){return this.data_variant[i];} return 0;}

				};
				HemiEngine.prepareObject("engine_object","%FILE_VERSION%",1,e);
				return e;

			};

	///		<method>
	///			<name>loadSpaces</name>
	///			<param name = "b" type = "boolean">Bit indicating that a primary engine should be defined if one is not specified.  This param will always be true if any engine exists and none are marked as primary.</param>
	///			<param name = "o" type = "object" optional = "1">Object in which to search for potential engine element declarations.</param>
	///			<param name = "pr" type = "function" optional = "1">Processor to assign to the engine.  Used for pre-processing XML templates and configuration.</param>
	///			<param name = "xr" type = "function" optional = "1">XML Handler to use when invoking setInnerXHTML.</param>
	///			<description>Finds all engine nodes on the current Web page and loads them.  An engine node is either an <i>engine</i> element, or a <i>div</i> element with an <i>is-engine</i> attribute.</description>
	///		</method>
			t.loadSpaces = function(b, d, pr, xr){
				/*
					b = switch used to force load the primary engine
					d = optional context to search for the engines
				
					o = task for engine
					m = array of engine elements
					e = element in a array
					i = iterator
					v = engine object instance
					s = default for engine; varies whether it is the primary engine
					x = method used to add task, varies whether it is the primary engine
					
					a = action
					at = action_type
					h = handler
					ht = handler_type
					
					l = length
					
					n = name
					z = id
					
					pn = page config task name
				*/

				var _p = t.objects,o,m=[],e,i,v,_s = t.properties,s = "p",x,_t,a,at,h,ht,l,n,z,c,p,q,pn;

				_t = _p.local_task_service;
				x = _t.addTaskLoader;
				
				if(document.body == null){
					this.logError("Space unable to initialize due to unexpected DOM.");
					return 0;
				}

				/*q = (d ? d : document).getElementsByTagName("engine");*/
				m.push(document.body);
				/*for(i=0;i<q.length;i++){ m[m.length]=q[i]; }*/

				p = _x.queryNodes((d ? d : document.body),"div",null,"is-space","1");
				for(i=0;i<p.length;i++){ m[m.length]=p[i]; }

				/*
					force load a primary space if no <engine /> tag was provided
				*/
				if(!b && !m.length && !_p.spaces.length) return t.loadSpaces(1);

				if(b){
					this.logDebug("Force load a primary space","1.2");
					m = [1];
				}
				
				for(i = 0;i < m.length; i++){
					if(!b) e = m[i];
					
					c = ++_s.space_id_counter;
					
					if(_p.spaces.length > 0){
						s = "d";
						x = _t.addTask;
						n = _s[s + "n"] + "_" + c;
					}
					else{
						n = _s[s + "n"];
					}
					
					z = _s.space_id_label + "_" + c;
					
					/* if forced, the element is invalid so check for !b */
					/*  && typeof e == DATATYPES.TYPE_OBJECT && e != null */
					if(!b){
						if(HemiEngine.IsAttributeSet(e,"name")){
							n = e.getAttribute("name");
						}
						else{
							e.setAttribute("name",n);
						}
						if(HemiEngine.IsAttributeSet(e,"engine-id")){
							z = e.getAttribute("engine-id");
						}
						else{
							e.setAttribute("engine-id",z);
						}
					}

					if(t.getSpaceByName(n)){
						this.logDebug("Space " + n + " (" + z + ") is already loaded.","1.3");
						continue;
					}

					if(!b && HemiEngine.IsAttributeSet(e,"space-action")){
						a = e.getAttribute("space-action");
					}
					else{
						a = _s[s + "a"];
					}
					if(!b && HemiEngine.IsAttributeSet(e,"space-action-type")){
						at = e.getAttribute("space-action-type");
					}
					else{
						at = _s[s + "at"];
					}
					if(!b && HemiEngine.IsAttributeSet(e,"space-handler")){
						h = e.getAttribute("space-handler");
					}
					else{
						h = _s[s + "h"];
					}
					if(!b && HemiEngine.IsAttributeSet(e,"space-handler-type")){
						ht = e.getAttribute("space-handler-type");
					}
					else{
						ht = _s[s + "ht"];
					}

					if(!b && HemiEngine.IsAttributeSet(e,"space-config-task")){
						_s.config_task = e.getAttribute("space-config-task");
					}
					
					o = x(
						n,
						at,
						a,
						ht,
						h
					);

					l = _p.spaces.length;
					
					v = t.newSpaceObject((b?0:e),z,n,o,l);
					if(pr) v.Processor = pr;
					if(xr) v.XhtmlHandler = xr;

					/*
						The first space is the primary.
					*/
					if(!l) v.is_primary = 1;
					/*
						add a dependency on the primary space to load
						and for the page_config_task to be complete
					*/
					else{
						_t.addTaskDependency(o,_s.pn);
						_t.addTaskDependency(o,_s.config_task);
					}
					t.addNewSpace(v, n, z);
					/*
					_p.spaces[l]=v;
					_p.enginenames[n]=l;
					_p.engineindex[z]=l;
					*/
					_t.executeTask(o);				
				}
			};

	///		<method>
	///			<name>bindElement</name>
	///			<param name = "o" type = "Space">A Space object.</param>
	///			<param name = "n" type = "DOM Node">An XML or HTML DOM Node.</param>
	///			<return-value name = "b" type = "boolean">True if the node was bound to the engine, false otherwise.</return-value>
	///			<description>Binds the specified node to the specified Engine object.</description>
	///		</method>
			t.bindElement = function(o, n){
				/*
					o = Space object
					n = node
				*/
				
				var 
					_s = t.properties,
					_p=t.objects,
					z,
					c,
					_a = Hemi.app.comp,
					r = 0
				;
				
				if(typeof o == DATATYPES.TYPE_STRING) o = t.getSpace(o);
				if(typeof n != DATATYPES.TYPE_OBJECT || !t.isEngine(o)) return 0;
				
				if(HemiEngine.IsAttributeSet(n,"rid"))
					r = n.getAttribute("rid");

				c = HemiEngine.object.xhtml.newInstance(n,1,r,o.engine_id,HemiEngine.data.form.service);

				l = o.space_objects.length;
				if(
					c != null
					&& 
					typeof c == DATATYPES.TYPE_OBJECT
					&&
					HemiEngine.registry.service.isRegistered(c)
					&&
					typeof o.space_object_index[c.object_id] != DATATYPES.TYPE_NUMBER
				){
					o.space_objects[l] = {object:c,config:"_bind",rid:r};
					o.space_object_index[c.object_id] = l;

					if(r && typeof o.space_object_names[r] != DATATYPES.TYPE_NUMBER){
						o.space_object_names[r] = l;
						this.logDebug("Register component '" + c.object_id + "' with friendly name '" + r + "'");
					}
					/*
					else{
						this.logDebug("Register component '" + c.object_id + "' without friendly name","200.1");
					}
					*/
				}

				if(c && c.object_type && c.object_type.match(/^xhtml_component$/)){
					c.post_init();
				}			

				return 1;

			};

	///		<method>
	///			<name>applyConfiguration</name>
	///			<param name = "o" type = "Space">A space object.</param>
	///			<param name = "c" type = "String">Name of SpaceService configuration.</param>
	///			<description>Applies the specified configuration to the specified engine.  This can be used to repurpose Space objects, or to load alternate content into the Space.</description>
	///		</method>
			t.applyConfiguration=function(o,c){
				/*
					o = Engine object
					c = config_name
					
					v = task object
					
					sf = self
				*/
				var v,_s = t.properties,s,_t = t.objects.local_task_service,_p=t.objects,i,a,sf=0;
				s = _s.config_default;

				v = _t.getTaskByName(_s.config_task);
				if(typeof o == DATATYPES.TYPE_STRING) o = t.getSpace(o);
				if(!c) c = "self";

				if(t.isEngine(o)){

					a = o.space_objects;
					for(i=a.length-1;i>=0;i--)
						HemiEngine.registry.service.sendDestroyTo(a[i].object);
					
					o.space_objects = [];
					o.space_object_names = [];
					o.space_object_index = [];
					
					o.space_implementations = [];
					
					/* only allow 'self' if the engine has an HTML element behind it */
					if(typeof c == DATATYPES.TYPE_STRING && c == "self" && o.space_element){
						sf = 1;
						s = sf;
					}

					if(!sf && o.space_element && o.space_element.getAttribute("space-config") != "self")
						_x.removeChildren(o.space_element);
						
					o.config_name = 0;
					/*
					 * 2004/07/21
					 * Change check for if task is complete it if the task was handled
					 */
					if(_t.isTask(v) && v.handled && typeof v.data == DATATYPES.TYPE_OBJECT){
						
						if(!sf && (o.space_element && HemiEngine.IsAttributeSet(o.space_element,"space-config")) || typeof c == DATATYPES.TYPE_STRING){
							s = (typeof c == DATATYPES.TYPE_STRING)?c:o.space_element.getAttribute("space-config");
							if(s && s=="self"){
								/* self can only be used once */
								o.space_element.removeAttribute("space-config");
								sf = 1;
							}
						}
						
						if(!s){
							this.logDebug("Page config not specified.");
							return 0;
						}
						o.config_name = c;

						this.logDebug("Process page config '" + s + "' for " + o.engine_name);

						t._parseConfiguration(o,v,s);
						
						o.space_implementations = [];
						
						_m.publish("onspaceconfigload",o);

					}
					else{
						this.logDebug("Page config not present.");
					}
				}
				else{
					this.logWarning("Invalid space reference for applyConfiguration","200.4");
				}
			};
			

			/*
			 * 2004/07/02
			 * 
			 * if page_config is 'self' then:
			 * a) don't validate page config
			 * b) don't copy any source
			 * 
			 */
			t._parseConfiguration=function(o,v,s,p,x,b){
				/*
					o = (validated) space object
					v = (validated) task object
					s = page config name
					p = parent node
					x = object instance
					b = return value of parent impl

					cs = current config name
					p = page config node
					a = array of nodes
					h = iterator
					i = iterator
					n = node
					
					q = node query
					
					d = def node
					
					r = tmp val
					m = tmp val
					w = tmp val
					u = tmp val
					g = tmp val
					j = tmp val
					k = tmp val
					y = tmp node
					z = tmp nodeset
					f = tmp val
					c = tmp val
					e = tmp val
					l = tmp val
					
					nl = node length
					
					br = block recursion
					
					cx = context switch
					cxn = context switch type (object_ref probably)
					cxp = context switch path as an xpath, probably
					
					ck = context parent; the output html node is the outbound parent node.  This is used when importing data into self referenced configurations
					cn = context swap name, used with ck
									
					ab = abstract implementation
					
					sf = bool: is self
					ci = cached implementation

				*/
				
				var a,i,n,q,d,r,m,u,g,j,y,z,f,b,c,h,k,l,e=0,w,br,cx,cxv,cxp,ab,nr,sf=0,ck,nl,ci;
				
				/* self must have an space_element, and that becomes the default parent */
				if(s == "self" && typeof p==DATATYPES.TYPE_UNDEFINED) p = o.space_element;
				else if(typeof p==DATATYPES.TYPE_UNDEFINED)
					p = _x.queryNode(v.data.documentElement,"configuration",0,"id",s);

				if(!p){
					_m.sendMessage("Page config for " + s + " not found.","200.4");
					return;
				}
				
				
				try{
				
				
					a = p.childNodes;
					nl = a.length;
					for(i=0;i<nl;i++){
						n = a[i];
						br = 1;

						/* g = namespace for implementation */
						/* k = bit used to specify whether the constructor is on the parent; eg: as with menuitems and resultitems */
						/* j = params array used when applying a constructor */

						d = ci = k = g = ab = cx = ck = 0;
						j = [];
						cs = s;
						
						if(s == "self") sf = 1;

						if(n.nodeType == 1){
							/*
							* 2008/02/07
							* Do not process nodes specifically marked for avoidance
							*
							*/
							if(n.getAttribute("avoid") == "1") continue;
							/*
							 * 2004/07/02
							 * Make sure to cast the node name to lower case
							 */
							q = n.nodeName.toLowerCase();
							
							/*
							 * 2004/07/20
							 * Cache experiment to try to improve performance on IE
							 * 
							 */
							
							w = o.space_implementations[q];
							if(w){

								k = w.p;
								cx = w.cs;
								cxp = w.cp;
								z = w.z;
								ab = w.ab;
								br = w.nr;
								sf = w.sf;
								ck = w.ck;
								g = w.g;
								f = w.f;
								/*j = w.j;*/
								y = w.y;
								cn = w.cn;
								ci = 1;

								%START_DEBUG_MESSAGE%
								_m.sendMessage("Process cached implementation for " + q,"200.1");
								%STOP_DEBUG_MESSAGE%
							}
							else d = t.getObjectDefinition(v.data,q);/*_x.selectSingleNode(v.data,"object-definitions/definition[@id = '" + q + "' or matdef[@rid = '" + q + "']]",v.data.documentElement);*/
							if(d){
								/* y = implementation node; re-used throughout statement */
								y = d.getElementsByTagName("implementation");/*_x.selectSingleNode(v.data,"implementation",d);*/
								if(y.length) y = y[0];
								else y = 0;
								
								/* process implementation for element */

								if(y){

									%START_DEBUG_MESSAGE%
									_m.sendMessage("Process implementation for " + q,"200.1");
									%STOP_DEBUG_MESSAGE%

									z = y.getElementsByTagName("package");/*_x.selectSingleNode(v.data,"package",y);*/
									if(z.length) z = z[0];
									else z = 0;
									
									k = (y.getAttribute("use-parent")=="1"?1:0);
									cx = (y.getAttribute("context-switch") == "1"?1:0);
									cxp = y.getAttribute("context-path");
									cn = y.getAttribute("swap-name");

									ab = (y.getAttribute("abstract")=="1"?1:0);
									br = (y.getAttribute("no-recursion")=="1"?0:1);

									/* if this is a self reference, and the context switched, then push config reference to switchedself */
									if(cx && cs == "self"){
										/*cs = "switchedself";*/

										%START_DEBUG_MESSAGE%
										_m.sendMessage("Switched off 'self' for context change in " + q,"200.1");
										%STOP_DEBUG_MESSAGE%
										sf = 0;
										ck = 1;
									}

									if(cxp) cxp = t._parseORAParam(o,v,cxp,n,x,b,p,cs);




									if(z && (u = z.getAttribute("pid")) && Engine.PackageExists(u)){
										g = Engine.GetPackage(u);
										
										if(g && (u = z.getAttribute("mid")) ){
											if(typeof g[u] == DATATYPES.TYPE_FUNCTION) g = g[u](t._parseORAParam(o,v,z.getAttribute("midparam"),n,x,b,p,cs));
										}
										
									}
									
									w = {};
									w.p = k;
									w.cs = cx;
									w.cp = cxp;
									w.z = z;
									w.ab = ab;
									w.nr = br;
									w.sf = sf;
									w.ck = ck;
									w.g = g;
									/*
									// assigned later w.f = f;
									// assigned later w.c
									// assigned later w.z
									w.j = j;
									*/
									w.y = y;
									w.cn = cn;
									o.space_implementations[q] = w;
									

								} /* end if (check_implemention) */
							
							} /* end  check for d */

							if(d || ci){
								
								if(ci){
									y = w.c;
								}
								else{
								
								y = y.getElementsByTagName("constructor");/*_x.selectSingleNode(v.data,"constructor[@name]",y);*/
								if(y.length) y = y[0];
								else y = 0;
								
								w.c = y;
								}
								
								
								/*
								 * 2004/07/21
								 * Don't cache the params because they include object
								 * references - everything would wind up being applied to
								 * the same object
								 */
								
								if(y){
									/*f = y.getAttribute("name");*/
									
									if(!ci){
									

										f = t._parseORAParam(o,v,y.getAttribute("name"),n,x,b,p,cs);
										
										z = y.getElementsByTagName("param");/*_x.selectNodes(v.data,"param",y);*/
									
										/*o.space_implementations[q].f = f;*/
										w.f = f;
										w.z = z;

									}
									else
										z = w.z;
											
									
									

									
									w = z.length;

									for(h = 0; h < w;){
										m = z[h++];
										u = 0;
										if(HemiEngine.IsAttributeSet(m,"value")){
											r = m.getAttribute("value");
											if(r.match(/^ora:/i))
												u = t._parseORAParam(o,v,r,n,x,b,p,cs);
											else
												u = r;
											
										}
										j[j.length]=u;
									}
								} /* end if (check_constructor) */
								
								/*
									g is a package
								*/
								nr = org.cote.js.GetSpecifiedAttribute(n, "%ENGINE_COMPONENT_AUTO_ID%");
								
								if(nr)
									n.setAttribute("id",nr + (++t.properties.space_autoid_counter));
								
								
								try{
								
									if(!ab){
										if(typeof g==DATATYPES.TYPE_OBJECT && g != null && typeof g[f] == DATATYPES.TYPE_FUNCTION){

											%START_DEBUG_MESSAGE%
											_m.sendMessage("apply #1 " + q + " : " + f,"200.1");
											%STOP_DEBUG_MESSAGE%

											w = g[f].apply(0,j);
										}
										else if(k && typeof x[f] == DATATYPES.TYPE_FUNCTION){

											%START_DEBUG_MESSAGE%
											_m.sendMessage("apply #2 " + q + " : " + f,"200.1");
											%STOP_DEBUG_MESSAGE%

											w = x[f].apply(x,j);
										}
										else{
											_m.sendMessage("Unexpected implementation with g=" + g + " and f=" + f,"200.4");
										}
									} /* end if not abstracted */
									else{
										/*
											Abstracted: just push out w to x
										*/ 
										%START_DEBUG_MESSAGE%
										_m.sendMessage("apply #3 " + q + " abstracted","200.1");
										%STOP_DEBUG_MESSAGE%
										w = x;
									} /* end if abstracted*/
								
								}
								catch(e){
									alert("Parse Configuration:" + (e.description?e.description:e.message) + " from f = " + f + " and " + x);
								}
								
								/* if use parent */
								if(k){
									e = w;
									w = x;
								} /* end if use parent*/
								
								/// if(q == "fragment") alert(cx + ":" + w);
								/*
								if(!w && ck && cn){
									k = document.createElement(cn);
									n.parentNode.appendChild(k);
									HemiEngine.xml.swapNode(k,n);
									
									%START_DEBUG_MESSAGE%
									_m.sendMessage("Swap Node 0 " + k.nodeName + " to " + n.nodeName + " in config " + s,"200.1");
									%STOP_DEBUG_MESSAGE%
								}
								*/
								/* if use context parent */
								/*
								if(ck){
									
								}
								*/
								/* end if context parent*/
								
								l = o.space_objects.length;
								/*
									reuse q
								*/

								q = org.cote.js.GetSpecifiedAttribute(n, "rid");

								if(
									w != null
									&& 
									typeof w==DATATYPES.TYPE_OBJECT
									&&
									HemiEngine.registry.service.isRegistered(w)
									&&
									typeof o.space_object_index[w.object_id] != DATATYPES.TYPE_NUMBER
								){
									o.space_objects[l] = {object:w,config:cs,rid:q};
									o.space_object_index[w.object_id] = l;
				
									if(q && typeof o.space_object_names[q] != DATATYPES.TYPE_NUMBER){
										o.space_object_names[q] = l;

										%START_DEBUG_MESSAGE%
										_m.sendMessage("Register component " + n.nodeName + " (" + w.object_id + ") with friendly name " + q,"200.1");
										%STOP_DEBUG_MESSAGE%

									}

									%START_DEBUG_MESSAGE%
									else{
										_m.sendMessage("Register component " + n.nodeName + " (" + w.object_id + ") without friendly name","200.1");
									}
									%STOP_DEBUG_MESSAGE%

								}

								/*
									A context switch is used for importing xml data, where the return value
									of the object implementation is an XML document, and cxp is null or an xpath.
								*/
								
								/*
								
									2008/11/04
									BUG BUG
									If the context switch parent (eg: import-xml) references an abstract,
									such as "html-fragment", the abstract needs to be swapped.
									
									Keep in mind caching rules must be considered. For example:
									
									<Template>
										<import-xml ...>[[EXTERN
											<html-fragment>
												<div>data</div>
											</html-fragment>]]
										</xml-xml>
									</Template>
								
								 * 
								 * 2004/07/02
								 * BUG BUG 
								 * For 'ck' implementations, setInnerXHTML can't use custom
								 * elements such as import-xml 
								 */

								if(cx && w){
									if(ck && cn){
										k = document.createElement(cn);
										n.parentNode.appendChild(k);
										HemiEngine.xml.swapNode(k,n);
										n.parentNode.removeChild(n);
										
										%START_DEBUG_MESSAGE%
										_m.sendMessage("Swap Node 1 " + k.nodeName + " to " + n.nodeName + " in config " + s,"200.1");
										%STOP_DEBUG_MESSAGE%

										/// n.swapped = 1;
										/*
										if(typeof k.swapNode != DATATYPES.TYPE_UNDEFINED)
											%START_DEBUG_MESSAGE%
											{
											
											_m.sendMessage("Swap Node " + k.nodeName + " to " + n.nodeName,"200.1");
											%STOP_DEBUG_MESSAGE%
											k.swapNode(n);
											
											%START_DEBUG_MESSAGE%
											}
											%STOP_DEBUG_MESSAGE%
										*/
										n = k;
									}
									if(!w.documentElement){
										%START_DEBUG_MESSAGE%
										_m.sendMessage("setInnerXHTML #1 " + q + " (1)","200.1");
										%STOP_DEBUG_MESSAGE%
										o.Processor(o,w);
										if(!sf) _x.setInnerXHTML(n,w,0,(!ck ? v.data : 0),0,0,0,o.XhtmlHandler);
										
									}
									else{
										/*
											If a data_path (dp) was used, assume it is for use to replace the context path from the config file.
										*/
										if(o.dp) cxp = o.dp;

										/* reuse nr */
				
										nr = (cxp?_x.selectSingleNode(w,cxp,w.documentElement):w.documentElement);
										if(!nr) nr = w.documentElement;

										%START_DEBUG_MESSAGE%
										_m.sendMessage("setInnerXHTML #2 " + q + " (1)","200.1");
										%STOP_DEBUG_MESSAGE%
										/*
										cx = n.getAttribute("%APPCOMP_BINDING_ID_ATTR%");
										k = 0;
										if(
											cx
											&&
											(q = HemiEngine.registry.service.getObject(cx))
										){
											k = q._handle_xhtml_token;
											n = q.getTemplateContainer();
										}
										*/
										o.Processor(o,nr);
										if(!sf) _x.setInnerXHTML(n,nr,0,(!ck ? v.data : 0),0,0,0,o.XhtmlHandler);

									}
									/*
										Switch the context back to the parent
									*/
									w = x;
								}
								
								if(br) t._parseConfiguration(o,v,cs,n,w,e);
								
								if(w && w.object_type && w.object_type.match(/^xhtml_component$/)){
									w.post_init();
								}
								
							} /* end check for implementation or cached implementation */
							else{
								/* just copy the whole node */
								
								if(typeof x == DATATYPES.TYPE_UNDEFINED) x = o;
								if(typeof x == DATATYPES.TYPE_OBJECT && x != null && typeof x.getContainer == DATATYPES.TYPE_FUNCTION){
									%START_DEBUG_MESSAGE%
									if(!sf) _m.sendMessage("setInnerXHTML #3 " + q + " (3)","200.1");
									%STOP_DEBUG_MESSAGE%
									o.Processor(o,n);
									if(!sf) _x.setInnerXHTML(x.getContainer(),n,true,0,0,0,0,o.XhtmlHandler);
								}
								%START_DEBUG_MESSAGE%
								else{
									_m.sendMessage("No object definition for " + n.nodeName + " (1); treating as HTML","200.1");
								}
								%STOP_DEBUG_MESSAGE%
							}
						}
						else if(n.nodeType == 3){
							if(n.nodeValue.replace(/\s/g,"").length && typeof x == DATATYPES.TYPE_OBJECT && typeof x.getContainer == DATATYPES.TYPE_FUNCTION){
									%START_DEBUG_MESSAGE%
									if(!sf) _m.sendMessage("setInnerXHTML #4 " + q + " (4)","200.1");
									%STOP_DEBUG_MESSAGE%
								o.Processor(o,n);
								if(!sf) _x.setInnerXHTML(x.getContainer(),n,1,0,0,0,0,o.XhtmlHandler);
							}
							%START_DEBUG_MESSAGE%
							else{
								_m.sendMessage("No object definition for " + n.nodeName + " (3); treating as HTML","200.1");
							}
							%STOP_DEBUG_MESSAGE%
						}

					} /* end for(i;childNodes.length) */
				
				}
				catch(e){
					_m.sendMessage("org.cote.js.engine.spaceservice._parseConfiguration Error: " +  (e.message ? e.message : e.description) ,"200.4");
					/* + "\n\n" + org.cote.js.error.traceRoute(t._parseConfiguration) */
				}
				

				%START_DEBUG_MESSAGE%
				var stop_parse = new Date().getTime();
				_m.sendMessage("_parseConfiguration Parse Time: " + (stop_parse - start_parse) + " for " + nl + " nodes","200.1");
				%STOP_DEBUG_MESSAGE%

			};
			/*
				ORA = object request alias; just a token that is used to reference a context object
			*/ 
			t._parseORAParam=function(o,v,r,e,x,b,q,s){
				/*
					o = engine object
					v = task object
					r = ora value
					e = originating xml element
					x = parent object instance
					b = parent reference; return value from where the parent object was created
					q = html parent
					s = config name
					
					a = variant used for name substring.
					z = return value;
					
					
					p = variant
					c = counter
					d = variant
					f = variant
				*/
				var z = 0,a,n,p,d,f,c,up,i;
				if(typeof r != DATATYPES.TYPE_STRING) return;
				r = r.replace(/^ora:/i,"");

				if(r.match(/(\S*)_parent$/i) ){
					r = r.match(/(\S*)_parent$/i)[1];
					up = 1;
				}

				if( r.match(/(\S*)_attr$/i) ){
					a = r.match(/(\S*)_attr$/i)[1];
	/*				r = r.replace(/(\S*)[^attr$]/i,"");*/
					r = "attr";
				}
				if( r.match(/integer_(\S*)$/i) ){
					a = r.match(/integer_(\S*)$/i)[1];
	/*				r = r.replace(/(\S*)[^attr$]/i,"");*/
					r = "integer";
				}
				if( r.match(/xpath-node-value:(\S*)/i)){
					a = r.match(/xpath-node-value:(\S*)/i)[1];
					r = "xpath-node-value";
	/*				r = r.replace(/(:\S*)[^xpath-node-value]/i,"");*/
				}
				if( r.match(/xpath-node-value-list:(\S*)/i)){
					a = r.match(/xpath-node-value-list:(\S*)/i)[1];
					r = "xpath-node-value-list";
	/*				r = r.replace(/(:\S*)[^xpath-node-value]/i,"");*/
				}

				switch(r){
					case "node_context":
						z = e;
						break;
					case "element_context":
						z = q;
						break;
					case "bool_true":
						z = 1;
						break;
					case "data_source":
						z = o.ds;
						break;
					case "parent_reference":
						z = b;
						break;
					case "xml_document":
						z = v.data;
						break;
					case "xpath-node-value-list":
						f = _x.selectNodes(v.data,a,e);
						p = [];
						for(c=0;c<f.length;c++){
							d = f[c];
							if(HemiEngine.IsAttributeSet(d,"value")){
								/*p[p.length] = d.getAttribute("value");*/
								p[p.length] = t._parseORAParam(o,v,d.getAttribute("value"),e,x,b,q,s);
							}
						}
						z = p;				
						break;
					case "xpath-node-value":
						n = _x.selectSingleNode(v.data,a,e);
						if(n){
							z = n.nodeValue;
						}
						break;
					case "params_array":
						a = e.getElementsByTagName("param");/*_x.selectNodes(v.data,"params/param",e);*/
						p = [];
						for(c=0;c<a.length;c++){
							d = a[c];
							if(HemiEngine.IsAttributeSet(d, "value")){
								p[p.length] = d.getAttribute("value");
							}
						}
						z = p;				
						break;
					case "integer":
						z = parseInt(a);
						if(isNaN(z)) z = 0;
						break;
					case "node_name":
						if(up){
							z = e.parentNode.nodeName;
						}
						else{
							z = e.nodeName;
						}
						break;
					case "attr":
						if(a){
							if(up){
								z = e.parentNode.getAttribute(a);
							}
							else{
								z = e.getAttribute(a);
							}
						}
						break;
	/*
					case "name_attr":
						z = e.getAttribute("name");
						break;
					case "url_attr":
						z = e.getAttribute("url");
						break;
					case "id_attr":
						z = e.getAttribute("id");
						break;
					case "value_attr":
						z = e.getAttribute("value");
						break;
	*/
					case "engine_object":
						z = o;
						break;
					case "engine_config":
						z = s;
						break;
					case "space_element":
						z = o[r];
						break;
					case "parent_element":
						if(typeof x == DATATYPES.TYPE_UNDEFINED) x = o;
						if(typeof x.getContainer == DATATYPES.TYPE_FUNCTION){
							z = x.getContainer();
						}
						break;
					case "engine_id":
						z = o.engine_id;
						break;
					default:

						%START_DEBUG_MESSAGE%
						_m.sendMessage("Unexpected/Pass-through ORA query: " + r,"200.4");
						%STOP_DEBUG_MESSAGE%

						z = r;
						break;
				}
				/*
					Just a fix-up for URLs so the engine id can be jacked into the query string.
					This was added to be picked up by the transformNode function in the HemiEngine.xml package,
					where the query params are jacked into the XML document element.
					
					This achieves the affect of (simply) passing parameters to the XML file, and thus, the XSL file.
				*/
				if(typeof z == DATATYPES.TYPE_STRING && z.match(/\?/) && z.match(/%ora:/)){
					up = z.substring(z.lastIndexOf("?")+1,z.length).split("&");
					for(c = 0;c<up.length;c++){
						d = up[c];
						if(!d.match(/%ora:/)) continue;
						n = new RegExp(d.match(/%ora:\S*%/));
						a = d.match(/%ora:(\S*)%/i)[1];
						if(a.match(/data_variant_\d*/)){
							i = parseInt(a.match(/data_variant_(\d*)/)[1]);
							if(isNaN(i)) i = -1;
							a = "data_variant";
						}
						r = 0;
						switch(a){
							case "eid":
								r = o.engine_id;
								break;
							case "data_variant":
								if(i >= 0){
									r = o.getDataVariant(i);
								}
								break;
							case "data_source":
								r = o.ds;
								break;

						}
						z = z.replace(n,r);
					}
				}
				return z;
			};
			
			t.getObjectDefinition = function(x, n){
				/*
				//object-definitions/definition[@id = '" + q + "' or matdef[@rid = '" + q + "']]",v.data.documentElement);	  
				 x = XML DOM
				 n = query name 
				 
				*/
				
				var o = 0,a,i=0,l,c,m,k,p,r;
				a = x.getElementsByTagName("definition");
				l = a.length;
				for(;i < l;){
					c = a[i++];
					if(c.getAttribute("id") == n){
						o = c;
						break;
					}
					
					m = c.getElementsByTagName("matdef");
					p = m.length;
					for(k = 0;k < p;){
						r = m[k++];
						if(r.getAttribute("rid") == n){
							/* if a matdef matches, then set the return value to the definition, not the matdef element */
							o = c;
							break;
						}
					}
					if(o) break;
				}
				return o;
					
			};
			
			t.handle_engine_started=function(s,v){
				
				/*
					Use the task_name to retrieve the reference to the engine instance.
					The engine name was used when creating the original task, so it should exist.
				*/
				
				var e;
				%START_DEBUG_MESSAGE%
				_m.sendMessage("Starting engine " + v.task.task_name,"200.1");
				%STOP_DEBUG_MESSAGE%
				if( typeof v == DATATYPES.TYPE_OBJECT && typeof v.task == DATATYPES.TYPE_OBJECT && (e = t.getSpaceByName(v.task.task_name)) ){
					if(e.is_primary){
						_m.sendMessage("Engine " + e.engine_id + " is the primary engine and should not be handled by this event.","200.5",1);
					}

					%START_DEBUG_MESSAGE%
					else{
						_m.sendMessage("Engine " + e.engine_id + " started","200.1");
					}
					%STOP_DEBUG_MESSAGE%

					t.applyConfiguration(e);
					_j.util.evaluateElementHandler(e.space_element,"engine-onload");
				}
				else{
					_m.sendMessage("Invalid engine reference for engine_started","200.4");
				}

			};
			
			t.handle_engine_service_initialized=function(){
				var _p = t.objects,e;
				%START_DEBUG_MESSAGE%
				_m.sendMessage("Starting engine service","200.1");
				%STOP_DEBUG_MESSAGE%
				if(_p.spaces.length){
					e = _p.spaces[0].space_element;
					t.applyConfiguration(_p.spaces[0]);
					HemiEngine.util.evaluateElementHandler(e,"engine-onload");
				}
	/*
				t.objects.task_service.returnDependency(t.properties.primary_engine_handler);
	*/
				return 1;
			};

			/*
				Add event buffer was designed for DOM events as a way
				of creating instance-specific handlers.
			*/

			HemiEngine._implements(t,"base_object","engine_service","%FILE_VERSION%");
			HemiEngine.object.addObjectAccessor(t,"space");
			
			_m.subscribe(t,"dom_event_window_load","handle_window_load");
			_m.subscribe(t,"engine_started","handle_engine_started");
			_m.subscribe(t,"engine_service_initialized","handle_engine_service_initialized");

			HemiEngine.registry.service.addObject(t);
			t.ready_state = 4;
		}
	}, 1);

}())
